// Package security @program: gateway
//@author: edte
//@create: 2021-12-29 09:14
package security

import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/dgrijalva/jwt-go"

	"gateway/tools/admin"
	"gateway/tools/user"
)

const (
	ErrorlessServerless = "服务器繁忙"
	ErrorlessReligions  = "请重新登陆"
)

var UserMap = make(map[int]string)

// JWTClaims token加密表单，解密后获取的信息
type JWTClaims struct { // token里面添加用户信息，验证token后可能会用到用户信息
	jwt.StandardClaims
	UserID      int      `json:"user_id"`
	Email       string   `json:"email"`
	Username    string   `json:"username"`
	FullName    string   `json:"full_name"`
	Permissions []string `json:"permissions"`
	Password    string
}

// JWTAdminClaims JWTClaims token加密表单，解密后获取的信息
type JWTAdminClaims struct { // token里面添加用户信息，验证token后可能会用到用户信息
	jwt.StandardClaims
	UserID int `json:"user_id"`
	//Email       string   `json:"email"`
	PrivilegeLevel int      `json:"privilege_level"`
	Username       string   `json:"username"`
	FullName       string   `json:"full_name"`
	Permissions    []string `json:"permissions"`
	Password       string
}

//	token的有效时间
var (
	Secret     = "dong_tech" // 加盐
	ExpireTime = 3600        // token有效期
)

// GetClaims 需写入token的用户信息
func GetClaims(uuid int, username string, password string, email string, nickname string) JWTClaims {
	claims := JWTClaims{
		UserID:      uuid,
		Username:    username,
		Password:    password,
		FullName:    nickname,
		Email:       email,
		Permissions: nil,
	}
	claims.IssuedAt = time.Now().Unix()
	claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
	return claims
}

//	GetToken 获取token码
func GetToken(claims *JWTClaims) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	signedToken, err := token.SignedString([]byte(Secret))
	if err != nil {
		return "", errors.New(ErrorlessServerless)
	}
	return signedToken, nil
}

// VerifyAction token解密
func VerifyAction(strToken string) (*JWTClaims, error) {
	token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(Secret), nil
	})
	if err != nil {
		return nil, errors.New(ErrorlessServerless)
	}
	claims, ok := token.Claims.(*JWTClaims)
	if !ok {
		return nil, errors.New(ErrorlessReligions)
	}
	if err := token.Claims.Valid(); err != nil {
		return nil, errors.New(ErrorlessReligions)
	}
	fmt.Println("verify")
	return claims, nil
}

// AdminVerifyAction VerifyAction token解密
func AdminVerifyAction(strToken string) (*JWTAdminClaims, error) {
	token, err := jwt.ParseWithClaims(strToken, &JWTAdminClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(Secret), nil
	})
	if err != nil {
		return nil, errors.New(ErrorlessServerless)
	}
	claims, ok := token.Claims.(*JWTAdminClaims)
	if !ok {
		return nil, errors.New(ErrorlessReligions)
	}
	if err := token.Claims.Valid(); err != nil {
		return nil, errors.New(ErrorlessReligions)
	}
	fmt.Println("verify")
	return claims, nil
}

/*// Refresh refresh token刷新
func Refresh(strToken string) (string, error) {
	claims, err := VerifyAction(strToken)
	if err != nil {
		return "", err
	}
	claims.ExpiresAt = time.Now().Unix() + (claims.ExpiresAt - claims.IssuedAt)
	signedToken, err := GetToken(claims)
	if err != nil {
		return "", err
	}
	return signedToken, err
}*/

func GetMytoken(user user.User) string {
	claims := GetClaims(user.Id, user.UserPhone, user.Password, user.EmailNumber, user.NickName)
	token, err := GetToken(&claims)
	if err != nil {
		log.Println(err)
	}
	return token
}

func GetAdminToken(user admin.UserAdmin) string {
	claims := GetAdminClaims(user.Id, user.AdminNum, user.AdminPD, user.PrivilegeLevel, user.AdminNum)
	token, err := getAdminToken(&claims)
	if err != nil {
		log.Println(err)
	}
	return token
}

// GetAdminClaims 需写入token的管理员用户信息
func GetAdminClaims(uuid int, username string, password string, Level int, nickname string) JWTAdminClaims {
	claims := JWTAdminClaims{
		UserID:         uuid,
		Username:       username,
		Password:       password,
		FullName:       nickname,
		PrivilegeLevel: Level,
		Permissions:    nil,
	}
	claims.IssuedAt = time.Now().Unix()
	claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
	return claims
}

//	GetToken 获取token码
func getAdminToken(claims *JWTAdminClaims) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	signedToken, err := token.SignedString([]byte(Secret))
	if err != nil {
		return "", errors.New(ErrorlessServerless)
	}
	return signedToken, nil
}
